package com.lin.service.impl;


import com.lin.common.constant.MessageConstant;
import com.lin.common.context.BaseContext;
import com.lin.common.exception.AccountException;
import com.lin.common.exception.BaseException;
import com.lin.common.result.Result;
import com.lin.entity.User;
import com.lin.entity.dto.UserDto;
import com.lin.mapper.UserMapper;
import com.lin.service.EmailSenderService;
import com.lin.service.RegisterService;
import com.lin.service.SendMsgService;
import com.lin.utils.myToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class RegisterServiceImpl implements RegisterService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EmailSenderService emailSenderService;

    @Autowired
    private SendMsgService sendMsgService;

    // 使用spring-security进行密码加密
    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);

    public String send(UserDto userDto) {
        log.info("发送验证码用户：{}", userDto);
        String token = null;
        if (userDto.getEmail() != null && !userDto.getEmail().equals("")) {
            User existingUserByEmail = userMapper.findByEmail(userDto.getEmail());
            // 检查邮箱或手机号是否已存在，防止重复注册
            if (existingUserByEmail != null) {
                throw new AccountException(MessageConstant.ALREADY_EXISTS_EMAIL);
            } else {
                //生成随机验证
                token = new myToken().creatToken();
                //保存token到redis
                redisTemplate.opsForValue().set(userDto.getEmail(), token, 5, TimeUnit.MINUTES);
                //发送邮箱校验
                SimpleMailMessage mailMessage = new SimpleMailMessage();
                mailMessage.setTo(userDto.getEmail());
                mailMessage.setSubject("注册验证码");
                mailMessage.setFrom("957554773@qq.com");
                mailMessage.setText("为完成注册认证, 请输入验证码\n" + "如非本人操作请忽略\n" + "（验证码有效期为5分钟）\n" + token);
                //发送
                emailSenderService.sendEmail(mailMessage);
            }
        }
        else if (userDto.getPhone() != null && !userDto.getPhone().equals("")) {
            User existingUserByPhone = userMapper.findByPhone(userDto.getPhone());
            if (existingUserByPhone != null) {
                throw new AccountException(MessageConstant.ALREADY_EXISTS_PHONE);
            }else {
                // 准备并发送短信验证码
                token = sendMsgService.sendMsg(userDto.getPhone());
                if (token == null) {
                    throw new BaseException("发送失败");
                }
                redisTemplate.opsForValue().set(userDto.getPhone(), token, 5, TimeUnit.MINUTES);

            }

        }
        return token;
    }

    public Result registerUser(UserDto userDto) {
        log.info("注册用户：{}", userDto);
        if (userDto.getEmail() != null && !userDto.getEmail().equals("")) {
            User existingUser = userMapper.findByEmail(userDto.getEmail());
            //如果邮箱已存在,不可注册
            if (existingUser != null) {
                throw new AccountException(MessageConstant.ALREADY_EXISTS);
            }
            //查询redis中的token
            String token = (String) redisTemplate.opsForValue().get(userDto.getEmail());
            //验证成功
            if (token == null) {
                throw new BaseException("验证码已过期，请重新发送");
            }
            if (token.equals(userDto.getToken())) {//激活
                redisTemplate.delete(userDto.getEmail());
                String pwd = encoder.encode(userDto.getPassword());
                userDto.setPassword(pwd);
                User user = new User();
                BeanUtils.copyProperties(userDto, user);
                userMapper.save(user);
                return Result.success();
            } else
                throw new BaseException(MessageConstant.TOKEN_ERROR);
        }else if (userDto.getPhone() != null && !userDto.getPhone().equals("")){
            User existingUser = userMapper.findByPhone(userDto.getPhone());
            if (existingUser != null) {
                throw new AccountException(MessageConstant.ALREADY_EXISTS);
            }
            //查询redis中的token
            String token = (String) redisTemplate.opsForValue().get(userDto.getPhone());
            //验证成功
            if (token == null) {
                throw new BaseException("验证码已过期，请重新发送");
            }
            if (token.equals(userDto.getToken())) {//激活
                redisTemplate.delete(userDto.getPhone());
                String pwd = encoder.encode(userDto.getPassword());
                userDto.setPassword(pwd);
                User user = new User();
                BeanUtils.copyProperties(userDto, user);
                userMapper.save(user);
                return Result.success();
            } else
                throw new BaseException(MessageConstant.TOKEN_ERROR);

        }
        return null;
    }

    /**
     * 重置密码
     * @param userDto
     */
    public void resetPassword(UserDto userDto) {
        User existingUser = userMapper.findByPhone(userDto.getPhone());
        if (existingUser == null) {
            throw new AccountException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        //查询redis中的token
        String token = (String) redisTemplate.opsForValue().get(userDto.getPhone());
        //验证成功
        if (token == null) {
            throw new BaseException("验证码已过期，请重新发送");
        }
        if (token.equals(userDto.getToken())) {
            redisTemplate.delete(userDto.getPhone());
            String pwd = encoder.encode(userDto.getPassword());
            existingUser.setPassword(pwd);
            userMapper.update(existingUser);
        } else
            throw new BaseException(MessageConstant.TOKEN_ERROR);
    }

    /**
     * 修改密码
     * @param userDto
     * @param password
     */
    public void changePassword(UserDto userDto, String password) {
        User existingUser = userMapper.findByPhone(userDto.getPhone());
        if (existingUser == null) {
            throw new AccountException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        if (encoder.matches(userDto.getPassword(), existingUser.getPassword())){
            String pwd = encoder.encode(password);
            existingUser.setPassword(pwd);
            userMapper.update(existingUser);
        }else {
            throw new BaseException(MessageConstant.PASSWORD_ERROR);
        }
    }

}
